package com.yu.crm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yu.crm.domain.pojo.AttendanceInfo;
import com.yu.crm.mapper.AttendanceInfoMapper;
import com.yu.crm.utils.HolidayUtil;
import com.yxzz.common.exception.GeneralException;
import com.yxzz.common.helper.DataHelpers;
import lombok.extern.log4j.Log4j2;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 考勤当天记录情况 服务实现类
 * </p>
 *
 * @author ct
 * @since 2019-12-31
 */
@Service
@Log4j2
@Transactional(rollbackFor = Exception.class)
public class AttendanceInfoService extends ServiceImpl<AttendanceInfoMapper, AttendanceInfo>{
    private static DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
    private static DateFormat df2 = new SimpleDateFormat("yyyy-MM");

    // EEEE表示星期几
    private static DateFormat df1 = new SimpleDateFormat("EEEE");

    /**
     * 通过月份及查询的用户编号查询考勤记录
     * @param queryMonth 月份(格式: yyyy-MM)
     * @param userId 查询的用户id
     * @return
     */
    public HashMap<String, Object> infoByQueryMonth(String queryMonth,String userId) {
        HashMap<String, Object> map=new HashMap<>();
        //1 正常 2 加班 3 迟到 4 早退 5 缺勤
        map.put("status1",0);
        map.put("status2",0);
        map.put("status3",0);
        map.put("status4",0);
        map.put("status5",0);
        map.put("items",new ArrayList<>());
        List<AttendanceInfo> attendanceInfos = baseMapper.listInfo(queryMonth, userId);
        if(DataHelpers.isNotEmpty(attendanceInfos)){
            Integer count1 = ((Long)attendanceInfos.stream().filter(x -> (x.getAmStatus() != 5 && x.getPmStatus() != 5)).count()).intValue();
            map.put("status1",count1);
            Integer count2 = ((Long)attendanceInfos.stream().filter(x -> x.getPmStatus()== 2).count()).intValue();
            map.put("status2",count2);
            Integer count3 = ((Long)attendanceInfos.stream().filter(x -> x.getAmStatus() == 3).count()).intValue();
            map.put("status3",count3);
            Integer count4 = ((Long)attendanceInfos.stream().filter(x -> x.getPmStatus() == 4).count()).intValue();
            map.put("status4",count4);
            map.put("status5",(attendanceInfos.size()-count1));
            map.put("items",attendanceInfos);
        }
        return map;
    }

    /**
     * 通过当前用户及当天查询是否有考勤记录
     * @param userId
     * @param queryMonth
     * @return
     */
    public AttendanceInfo infoByUserId(String userId, String queryMonth){
        QueryWrapper<AttendanceInfo> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("user_id",userId);
        queryWrapper.eq("record_time",queryMonth);
        queryWrapper.eq("is_deleted",0);
        try {
            AttendanceInfo attendanceInfo = baseMapper.selectOne(queryWrapper);
            if(DataHelpers.isNotEmpty(attendanceInfo)){
                log.info("通过当前用户及当天查询是否有考勤记录成功");
            }
            return attendanceInfo;
        }catch (Exception e){
            e.printStackTrace();
            log.error("通过当前用户及当天查询是否有考勤记录失败");
            throw new GeneralException("通过条件查询考勤设置数据失败");
        }
    }


    /**
     * 根据当前时间判断是否需要记录考勤，并设置缺勤记录
     */
    public void addStatusFive(){
        //当前时间
        String formatYmd =df.format(new Date());
        Integer request = HolidayUtil.request(formatYmd);
        if(request==0){
            List<String> userIds = baseMapper.listUserId(formatYmd);
            if(DataHelpers.isNotEmpty(userIds)){
                List<AttendanceInfo> list=new ArrayList<>();

                for(String userId:userIds){
                    AttendanceInfo attendanceInfo = infoByUserId(userId, formatYmd);
                    if(DataHelpers.isEmpty(attendanceInfo)){
                        attendanceInfo=new AttendanceInfo();
                        attendanceInfo.setUserId(userId);
                        attendanceInfo.setRecordTime(formatYmd);
                        attendanceInfo.setAmStatus(5);
                        attendanceInfo.setPmStatus(5);
                        attendanceInfo.setStatus(3);
                        attendanceInfo.setGmtCreate(LocalDateTime.now());
                        attendanceInfo.setGmtModified(LocalDateTime.now());

                        list.add(attendanceInfo);
                    }
                }
                if(DataHelpers.isNotEmpty(list)){
                    saveBatch(list);
                }
            }
        }
    }

    /**
     * 通过月份及查询的用户编号查询考勤记录并生成excel文档
     * @param queryMonth 月份(格式: yyyy-MM)
     * @return
     */
    public void excelByQueryMonth(HttpServletRequest request, HttpServletResponse response, String queryMonth) {
        //月份最大一天
        Integer monthMaxDay = getMonthMaxDay(queryMonth);
        Integer len=(monthMaxDay+6);
        String title=(queryMonth.replace("-","年")+"月出勤统计");
        String dowloadExcelDate=df.format(new Date());
        try {
            XSSFWorkbook wb = new XSSFWorkbook();
            // 创建工作表
            XSSFSheet sheet = wb.createSheet(title);
            // 比如我要合并 第二行到第四行的 第六列到第八列 sheet.addMergedRegion(new CellRangeAddress(1,3,5,7));
            // 参数说明：1：开始行 2：结束行 3：开始列 4：结束列
            //第一行
            sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, len));
            //第二行
            sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, len-5));
            sheet.addMergedRegion(new CellRangeAddress(1, 1, len-4, len));
            //第三到四行
            sheet.addMergedRegion(new CellRangeAddress(2, 3, 0, 0));
            //第三行
            sheet.addMergedRegion(new CellRangeAddress(2, 2, len-4, len));


            //设置所有单元格宽度
            //sheet.setDefaultColumnWidth(13);
            Row row;// 创建行对象
            Cell cell;// 创建格子对象

            //其他行
            CellStyle cellStyle = wb.createCellStyle();


            //其他行默认设置
            XSSFFont font = wb.createFont();
            //font3.setBold(true);
            font.setFontName("宋体");// 字体
            font.setFontHeight(11);
            cellStyle.setFont(font);// 使用字体
            cellStyle.setWrapText(true); //换行显示
            cellStyle.setAlignment(HorizontalAlignment.CENTER); // 居中格式
            cellStyle.setLocked(true);// 只读

            //设置前四行值
            excel(title,queryMonth,dowloadExcelDate,sheet,wb,len);

            //查询用户当前月考勤情况
            List<AttendanceInfo> infos = baseMapper.listInfo(queryMonth, "");
            if(DataHelpers.isNotEmpty(infos)){
                //第五行
                int rowCount=4;
                Map<String, List<AttendanceInfo>> map = infos.stream().collect(Collectors.groupingBy(AttendanceInfo::getUserId));
                for(String userId:map.keySet()){
                    //第rowCount到rowCount+1行
                    sheet.addMergedRegion(new CellRangeAddress(rowCount, rowCount+1, 0, 0));
                    //第rowCount行
                    sheet.addMergedRegion(new CellRangeAddress(rowCount, rowCount+1, len-4, len-4));
                    sheet.addMergedRegion(new CellRangeAddress(rowCount, rowCount+1, len-3, len-3));
                    sheet.addMergedRegion(new CellRangeAddress(rowCount, rowCount+1, len-2, len-2));
                    sheet.addMergedRegion(new CellRangeAddress(rowCount, rowCount+1, len-1, len-1));
                    sheet.addMergedRegion(new CellRangeAddress(rowCount, rowCount+1, len, len));

                    //考勤记录集合
                    List<AttendanceInfo> value = map.get(userId);
                    String userName = value.get(0).getUserName();


                    Integer count1 = ((Long)value.stream().filter(x -> (x.getAmStatus() != 5 && x.getPmStatus() != 5)).count()).intValue();
                    Integer count2 = ((Long)value.stream().filter(x -> x.getPmStatus()== 2).count()).intValue();
                    Integer count3 = ((Long)value.stream().filter(x -> x.getAmStatus() == 3).count()).intValue();
                    Integer count4 = ((Long)value.stream().filter(x -> x.getPmStatus() == 4).count()).intValue();
                    Integer count5=(value.size()-count1);


                    for(Integer i=0;i<2;i++){
                        //从第5行开始创建
                        row = sheet.createRow(rowCount+i);
                        for(int x=0;x<=len;x++){
                            cell = row.createCell(x);
                            if(i!=1){
                                //第一行
                                if(x==0){
                                    cell.setCellValue(userName);
                                }else if(x==1){
                                    cell.setCellValue("上午");
                                }else if(x==(len-4)){
                                    cell.setCellValue(count1);
                                }else if(x==(len-3)){
                                    cell.setCellValue(count2);
                                }else if(x==(len-2)){
                                    cell.setCellValue(count3);
                                }else if(x==(len-1)){
                                    cell.setCellValue(count4);
                                }else if(x==len){
                                    cell.setCellValue(count5);
                                }else{
                                    Integer x3= (x - 1);
                                    String month1="";
                                    if(x3<10){
                                        month1=queryMonth+"-0"+x3;
                                    }else{
                                        month1=queryMonth+"-"+x3;
                                    }
                                    for(AttendanceInfo info:value){
                                        if(month1.equals(info.getRecordTime())){
                                            if(DataHelpers.isNotEmpty(info.getAmTime())){
                                                cell.setCellValue(info.getAmTime());
                                            }else{
                                                if(info.getAmStatus()==5){
                                                    cell.setCellValue("缺勤");
                                                }
                                            }
                                        }
                                    }
                                }
                            }else{
                                //第二行
                               if(x==1){
                                    cell.setCellValue("下午");
                               }else if(x==(len-4)){
                                   cell.setCellValue(count1);
                               }else if(x==(len-3)){
                                   cell.setCellValue(count2);
                               }else if(x==(len-2)){
                                   cell.setCellValue(count3);
                               }else if(x==(len-1)){
                                   cell.setCellValue(count4);
                               }else if(x==len){
                                   cell.setCellValue(count5);
                               }else{
                                   Integer x3= (x - 1);
                                   String month1="";
                                   if(x3<10){
                                       month1=queryMonth+"-0"+x3;
                                   }else{
                                       month1=queryMonth+"-"+x3;
                                   }
                                   for(AttendanceInfo info:value){
                                       if(month1.equals(info.getRecordTime())){
                                           if(DataHelpers.isNotEmpty(info.getPmTime())){
                                               cell.setCellValue(info.getPmTime());
                                           }else{
                                               if(info.getAmStatus()==5){
                                                   cell.setCellValue("缺勤");
                                               }
                                           }
                                       }
                                   }
                               }
                            }
                            cell.setCellStyle(cellStyle);
                        }
                    }
                    rowCount=rowCount+2;
                }
            }

            try {
                // 下载文件的默认名称
                response.setHeader("Content-disposition",
                        "attachment;filename=" + URLEncoder.encode(title+ "-"+dowloadExcelDate+
                                ".xlsx", "UTF-8"));
                // 创建Excel对象
                // 写出流
                wb.write(response.getOutputStream());
            } catch (Exception e) {
                e.printStackTrace();
                throw new Exception("文件下载失败");
            } finally {
                if (wb != null) {
                    try {
                        wb.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }catch (GeneralException e){
            throw new GeneralException(e.getMessage());
        }catch (Exception e){
            e.printStackTrace();
            log.error("生成excel错误");
            throw new GeneralException("生成excel错误");
        }
    }

    /**
     * 通过年月查询本月最大一天
     * @param month  yyyy-MM
     * @return
     */
     private Integer getMonthMaxDay(String month){
        try {
            //获取当前月最后一天
            Calendar ca = Calendar.getInstance();
            ca.setTime(df2.parse(month));
            ca.add(Calendar.MONTH, 1);
            ca.set(Calendar.DAY_OF_MONTH, 0);
            Integer monthMaxDay= ca.get(Calendar.DATE);
            if(DataHelpers.isNotInteger(monthMaxDay)){
                return monthMaxDay;
            }else{
                log.error("查询当前月最大一天错误");
                throw new GeneralException("查询当前月最大一天错误");
            }
        }catch (GeneralException e){
            log.error("查询当前月最大一天错误");
            throw new GeneralException("查询当前月最大一天错误");
        }catch (Exception e){
            e.printStackTrace();
            log.error("查询当前月最大一天错误");
            throw new GeneralException("查询当前月最大一天错误");
        }
    }

    /**
     * 设置excel前四行值
     * @param title 标题
     * @param month 年月 yyyy-MM
     * @param dowloadExcelDate 导出时间
     * @param sheet
     * @param wb
     * @param len 总列数
     * @throws Exception
     */
    private void excel(String title,String month,String dowloadExcelDate,XSSFSheet sheet,XSSFWorkbook wb,Integer len) throws Exception{
        //设置样式(前四行) 第一行
        CellStyle cellStyle0 = wb.createCellStyle();
        CellStyle cellStyle1 = wb.createCellStyle();
        CellStyle cellStyle2 = wb.createCellStyle();
        CellStyle cellStyle3 = wb.createCellStyle();

        //第一行设置字体颜色
        XSSFFont font0 = wb.createFont();
        //粗体
        font0.setBold(true);
        // 字体
        font0.setFontName("宋体");
        // 大小
        font0.setFontHeight(15);
        cellStyle0.setFont(font0);// 使用字体
        cellStyle0.setWrapText(true); //换行显示
        cellStyle0.setAlignment(HorizontalAlignment.CENTER); // 居中格式

        //第二行设置字体颜色
        XSSFFont font1 = wb.createFont();
        font1.setBold(false);
        font1.setFontName("宋体");// 字体
        font1.setFontHeight(12);
        cellStyle1.setFont(font1);// 使用字体
        cellStyle1.setWrapText(true); //换行显示
        cellStyle1.setAlignment(HorizontalAlignment.CENTER); // 居中格式
        cellStyle1.setLocked(true);// 只读

        //第三行设置字体颜色
        XSSFFont font2 = wb.createFont();
        font2.setBold(true);
        font2.setFontName("宋体");// 字体
        font2.setFontHeight(12);
        cellStyle2.setFont(font2);// 使用字体
        cellStyle2.setWrapText(true); //换行显示
        cellStyle2.setAlignment(HorizontalAlignment.CENTER); // 居中格式
        cellStyle2.setLocked(true);// 只读


        //第四行设置字体颜色
        XSSFFont font3 = wb.createFont();
        font3.setBold(false);
        font3.setFontName("宋体");// 字体
        font3.setFontHeight(11);
        //设置字体颜色
        //font3.setColor(IndexedColors.RED1.getIndex());
        cellStyle3.setFillForegroundColor(IndexedColors.YELLOW.index);
        cellStyle3.setFont(font3);// 使用字体
        cellStyle3.setWrapText(true); //换行显示
        cellStyle3.setAlignment(HorizontalAlignment.CENTER); // 居中格式
        cellStyle3.setLocked(true);// 只读

        List<CellStyle> styles=new ArrayList<>();
        styles.add(cellStyle0);
        styles.add(cellStyle1);
        styles.add(cellStyle2);
        styles.add(cellStyle3);

        Row row;
        Cell cell;

        // 创建第一行
        row = sheet.createRow(0);
        cell = row.createCell(0);
        cell.setCellValue(title);
        cell.setCellStyle(styles.get(0));
        row.setHeight((short) 400);

        // 创建第二行
        row = sheet.createRow(1);
        for(int x1=0;x1<=len;x1++){
            cell = row.createCell(x1);
            if(x1<=(len-5)){
                cell.setCellValue("喻信中智(武汉)信息技术有限公司");
            }else{
                cell.setCellValue("导出时间:"+dowloadExcelDate);
            }
            cell.setCellStyle(styles.get(1));
        }

        // 创建第二行
        row = sheet.createRow(2);
        for(int x2=0;x2<=len;x2++){
            cell = row.createCell(x2);
            if(x2==0){
                cell.setCellValue("姓名");
            }else if(x2==1){
                cell.setCellValue("日期");
            }else if(x2==(len-4)){
                cell.setCellValue("合计");
            }else{
                cell.setCellValue(x2-1);
            }
            cell.setCellStyle(styles.get(2));
        }

        // 创建第二行
        row = sheet.createRow(3);
        for(int x2=0;x2<=len;x2++){
            cell = row.createCell(x2);
           if(x2==1){
               cell.setCellValue("星期");
           }else if(x2==(len-4)){
               cell.setCellValue("出勤");
           }else if(x2==(len-3)){
               cell.setCellValue("加班");
           }else if(x2==(len-2)){
               cell.setCellValue("迟到");
           }else if(x2==(len-1)){
               cell.setCellValue("早退");
           }else if(x2==len){
               cell.setCellValue("缺勤");
           }else{
               Integer x3= (x2 - 1);
               String month1="";
               if(x3<10){
                   month1=month+"-0"+x3;
               }else{
                   month1=month+"-"+x3;
               }
               //处理日期，返回星期几
               String weekDay = df1.format(df.parse(month1)).replace("星期", "");
               Integer request = HolidayUtil.request(month1);
               if(DataHelpers.isNotEmpty(weekDay)){
                   if(weekDay.equals("Monday")){
                       weekDay="一";
                   }else if(weekDay.equals("Tuesday")){
                       weekDay="二";
                   }else if(weekDay.equals("Wednesday")){
                       weekDay="三";
                   }else if(weekDay.equals("Thursday")){
                       weekDay="四";
                   }else if(weekDay.equals("Friday")){
                       weekDay="五";
                   }else if(weekDay.equals("Saturday")){
                       weekDay="六";
                   }else if(weekDay.equals("Sunday")){
                       weekDay="日";
                   }
               }
               if(request!=0){
                   weekDay=weekDay+"/休";
               }
               cell.setCellValue(weekDay);
           }
            cell.setCellStyle(styles.get(3));
        }
    }

    public AttendanceInfo infoByDay(String queryDay, String userId) {
        QueryWrapper<AttendanceInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id",userId);
        queryWrapper.eq("record_time",queryDay);
        queryWrapper.eq("is_deleted",0);
        return baseMapper.selectOne(queryWrapper);
    }
}
